package com.sudo.rpc.server.client;

import com.alibaba.fastjson2.JSON;
import com.sudo.rpc.api.common.Constant;
import com.sudo.rpc.api.model.CallTask;
import com.sudo.rpc.api.model.RegistryServer;
import com.sudo.rpc.api.service.RmiSetServerService;
import com.sudo.rpc.api.utils.RpcRes;
import com.sudo.rpc.server.config.FxwRpcProperties;
import com.sudo.rpc.server.task.registry.BaseTaskRegistry;
import com.sudo.rpc.server.utils.SpringContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;

import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.Map;

@Slf4j
public class ClientRmiRegistryServiceImpl extends UnicastRemoteObject implements RmiSetServerService {

    @Resource
    private FxwRpcProperties fxwRpcProperties;

    public ClientRmiRegistryServiceImpl() throws RemoteException {

    }

    @Override
    public void pushServer(RegistryServer registryServer) throws RemoteException {
        String remoteRegistryIp = fxwRpcProperties.getRemoteRegistryIp();
        Integer remoteRegistryPort = fxwRpcProperties.getRemoteRegistryPort();
        log.info("连接管理端服务："+ remoteRegistryIp +":" + remoteRegistryPort + " 注册中心");

        try {
            Registry remoteRegistry = LocateRegistry.getRegistry(remoteRegistryIp, remoteRegistryPort);
            RmiSetServerService rmiSetServerService = (RmiSetServerService) remoteRegistry.lookup(Constant.registryCenter);
            // 4.将本地服务地址发送给管理端
            rmiSetServerService.pushServer(registryServer);
        } catch (NotBoundException e) {
            log.error("服务注册失败：",e);
        }
    }

    @Override
    public Object pullServer(String ip,Integer port) throws RemoteException {
        return BaseTaskRegistry.getRegistryServer();
    }

    @Override
    public Object callServer(CallTask callTask) throws RemoteException{
        String beanName = callTask.getBeanName();
        String methodName = callTask.getMethodName();
        String methodParams = callTask.getMethodParams();
        log.info("方法被调用：{}-{}-{}",beanName,methodName,methodParams);

        Class<?> aClass = BaseTaskRegistry.getClassByBean(beanName);

        Object bean = SpringContextUtil.getBean(beanName);
        Method declaredMethod;
        try {
            if (StringUtils.isBlank(methodParams)) {
                declaredMethod = aClass.getDeclaredMethod(methodName);
                return declaredMethod.invoke(bean);
            }else {
                declaredMethod = aClass.getDeclaredMethod(methodName, Map.class);
                Map paramMap = JSON.parseObject(methodParams,Map.class);
                return declaredMethod.invoke(bean,paramMap);
            }
        } catch (NoSuchMethodException e) {
            log.error("找不到方法异常：",e);
            String stackTrace = ExceptionUtils.getStackTrace(e);
            return RpcRes.error(stackTrace,"找不到方法异常：" + e.getCause());
        } catch (IllegalAccessException e) {
            log.error("非法访问异常：",e);
            String stackTrace = ExceptionUtils.getStackTrace(e);
            return RpcRes.error(stackTrace,"非法访问异常：" + e.getCause());
        } catch (InvocationTargetException e) {
            String stackTrace = ExceptionUtils.getStackTrace(e);
            log.error("调用异常：",e);
            return RpcRes.error(stackTrace,"调用异常：" + e.getCause());
        }
    }
}
